﻿using System.Windows;
using System.Windows.Interactivity;

namespace Kinect.Viewer.Behaviors
{
    /// <summary>
    /// Behavior gérant le chargement et le déchargement depuis l'arbre visuel.
    /// </summary>
    /// <typeparam name="T">Le type d'élément sur lequel ce behavior peut être appliqué.</typeparam>
    public class LoadedAwareBehavior<T> : Behavior<T>
    where T : FrameworkElement
    {
        private bool _loadedRegistered;
        private bool _unloadedRegistered;

        private void RegisterLoaded()
        {
            AssociatedObject.Loaded += AssociatedObject_Loaded;
            _loadedRegistered = true;
        }

        private void UnregisterLoaded()
        {
            AssociatedObject.Loaded -= AssociatedObject_Loaded;
            _loadedRegistered = false;
        }

        private void RegisterUnloaded()
        {
            AssociatedObject.Unloaded += AssociatedObject_Unloaded;
            _unloadedRegistered = true;
        }

        private void UnregisterUnloaded()
        {
            AssociatedObject.Unloaded -= AssociatedObject_Unloaded;
            _unloadedRegistered = false;
        }

        /// <summary>
        /// Méthode appelée lorsque le behavior est attaché à un élément.
        /// </summary>
        protected sealed override void OnAttached()
        {
            base.OnAttached();
            if (AssociatedObject.IsLoaded)
            {
                RegisterUnloaded();
                OnLoaded();
            }
            else
                RegisterLoaded();
        }

        /// <summary>
        /// Méthode appelée lorsque le behavior est détaché d'un élément.
        /// </summary>
        protected sealed override void OnDetaching()
        {
            if (_loadedRegistered)
                UnregisterLoaded();
            if (_unloadedRegistered)
                UnregisterUnloaded();
            base.OnDetaching();
        }

        /// <summary>
        /// Méthode appelée lorsque l'élément attaché est chargé dans un arbre visuel.
        /// </summary>
        protected virtual void OnLoaded()
        {
        }

        /// <summary>
        /// Méthode appelée lorsque l'élément attaché est déchargé d'un arbre visuel.
        /// </summary>
        protected virtual void OnUnloaded()
        {
        }

        private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
        {
            UnregisterLoaded();
            RegisterUnloaded();
            OnLoaded();
        }

        private void AssociatedObject_Unloaded(object sender, RoutedEventArgs e)
        {
            UnregisterUnloaded();
            RegisterLoaded();
            OnUnloaded();
        }

    }
}